package com.login.sotoken.controller.user;

import cn.dev33.satoken.annotation.SaCheckDisable;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.dev33.satoken.util.SaResult;
import com.login.sotoken.common.AjaxJson;
import com.login.sotoken.req.LoginListReq;
import com.login.sotoken.resp.LoginGetResp;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

/**
 * 登录测试
 *
 * @author click33
 */
@Slf4j
@Tag(name = "管理端登录管理", description = "管理端登录管理接口")
@RestController
@RequestMapping("/acc/")
public class AdminLoginController {

    @Operation(summary = "登录")
    @PostMapping("doLogin")
    public SaResult doLogin(@Valid @RequestBody LoginListReq req) {
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对
        if ("zhang".equals(req.getUsername()) && "123456".equals(req.getPassword())) {
//			StpUtil.login(req.getUsername(),req.getDeviceType());
            StpUtil.login(10001, new SaLoginParameter()
                    .setDevice(req.getDeviceType())   // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
                    .setIsLastingCookie(true)        // 是否为持久Cookie（临时Cookie在浏览器关闭时会自动删除，持久Cookie在重新打开后依然存在）
                    .setTimeout(60 * 60 * 24 * 7)    // 指定此次登录token的有效期, 单位:秒 （如未指定，自动取全局配置的 timeout 值）
                    .setIsWriteHeader(false)         // 是否在登录后将 Token 写入到响应头
            );
            LoginGetResp loginGetResp = new LoginGetResp();
            BeanUtils.copyProperties(req, loginGetResp);
            loginGetResp.setToken(StpUtil.getTokenInfo().getTokenValue());
            return SaResult.data(loginGetResp);
        }
        return SaResult.error("登录失败");
    }

    @Operation(summary = "查询登录状态")
    @GetMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登录：" + StpUtil.isLogin());
    }

    @Operation(summary = "获取token信息")
    @GetMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }

    @Operation(summary = "退出登录")
    @GetMapping("logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }

    /**
     * 强制注销等价于对方主动调用了注销方法，再次访问会提示：Token无效。
     * 踢人下线不会清除Token信息，而是将其打上特定标记，再次访问会提示：Token已被踢下线。
     */
    @Operation(summary = "强制注销")
    @GetMapping("logoutForce")
    public SaResult logoutForce(@Schema(description = "用户名") @RequestParam(name = "userName", defaultValue = "10001") String userName,
                                @Schema(description = "设备类型") @RequestParam(name = "deviceType", defaultValue = "PC") String deviceType) {
        StpUtil.logout(userName, deviceType);
        return SaResult.ok();
    }

    @Operation(summary = "踢人下线")
    @GetMapping("kickOut")
    public SaResult kickOut(@Schema(description = "用户名", required = true) @NotBlank(message = "用户名不能为空") @RequestParam(name = "userName", defaultValue = "10001") String userName,
                            @Schema(description = "设备类型") @RequestParam(name = "deviceType", defaultValue = "PC") String deviceType) {
        StpUtil.kickout(userName, deviceType);
        return SaResult.ok();
    }

    /**
     * 账号封禁
     */
    @Operation(summary = "封禁-api")
    @GetMapping("disable")
    public SaResult disable(@Schema(description = "用户名", required = true) @NotBlank(message = "用户名不能为空") @RequestParam(name = "userName", defaultValue = "10001") String userName) {
        //1.基本使用
        //封禁指定账号
        StpUtil.disable(userName, 86400);
        //封禁指定账号，指定服务
        StpUtil.disable(userName, "comment", 86400);
        //查询剩余封禁的时间
        long timeDisable = StpUtil.getDisableTime(userName);
        //解除封禁
        StpUtil.untieDisable(userName);
        log.info("剩余封禁时间：" + timeDisable);
        //2.阶梯封禁
        // 阶梯封禁，参数：封禁账号、封禁级别、封禁时间
        StpUtil.disableLevel(userName, 3, 86400);
        //获取：指定账号封禁的级别 （如果此账号未被封禁则返回 -2）
        StpUtil.getDisableLevel(userName);
        // 判断：指定账号是否已被封禁到指定级别，返回 true 或 false
        StpUtil.isDisableLevel(10001, 3);
        // 校验：指定账号是否已被封禁到指定级别，如果已达到此级别（例如已被3级封禁，这里校验是否达到2级），则抛出异常 `DisableServiceException`
        StpUtil.checkDisableLevel(10001, 2);
        return SaResult.ok();

    }

    @Operation(summary = "注解校验当前账号是否被封禁comment服务")
    @SaCheckDisable("comment")
    @GetMapping("send")
    public AjaxJson send() {
        return AjaxJson.getSuccess("前账号没被封禁comment服务");
    }

    /**
     * 创建账号对密码加密
     */
    @Operation(summary = "创建账号对密码加密")
    @PostMapping("creat")
    public AjaxJson creat(@RequestBody @Valid LoginListReq req) {
        String s = SaSecureUtil.md5(req.getPassword());
        req.setPassword(s);
        return AjaxJson.getSuccessData(req);
    }
}
